package org.streets.database.internal;

import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.streets.commons.util.JDBCUtils;
import org.streets.database.PV;
import org.streets.database.SQLBatcher;
import org.streets.database.SQLNestedException;
import org.streets.database.SQLUtils;
/**
 * 名字参数SQL执行器
 * @author dzb
 */
public final class SQLBatcherImpl implements SQLBatcher {

	private transient PreparedStatement pstmt = null;
	private final String sql;
	private final String[] param_names;
	private final int[] param_types;
	
	SQLBatcherImpl(PreparedStatement pstmt, String sql, String[] names) {
		this.pstmt = pstmt;
		this.sql = sql;
		this.param_names = names;
		this.param_types = null;
	}

	SQLBatcherImpl(PreparedStatement pstmt, String sql, String[] names, int[] types) {
		this.pstmt = pstmt;
		this.sql = sql;
		this.param_names = names;
		this.param_types = types;
	}    

	public <T> SQLBatcher add(T bean) {
		Object[] params = null;
		try {
			params = SQLUtils.buildJPAFieldValues(param_names, bean);			
		} catch (Exception e) {
			throw new SQLNestedException("Build bean["+bean.getClass()+"] params value error !!!", e);
		}
		return add(params);
	}
	
    public SQLBatcher add(PV... values) {
    	Object[] params = SQLUtils.buildNamedParamValues(param_names, values);
    	return add(params);
    }
    /**
     * Use PV.of() method to generate Object[] values
     */
    public SQLBatcher add(Object[] params) {
    	try {	    	
	        if (param_types == null) {
	        	JDBCUtils.bindParameters(pstmt, params);
	        } else {
	        	JDBCUtils.bindParameters(pstmt, params, param_types);
	        }
	        pstmt.addBatch();
	        return this;
    	} catch (SQLException ex) {
    		JDBCUtils.close(pstmt);
            JDBCUtils.logError("DBERROR OCCURS: \\r\\n CODE-" + ex.getErrorCode()
                    + "  MESSAGE: " + ex.getMessage(), ex);
            throw new SQLNestedException(ex);
    	}
    }

    public int[] execute() {
    	try {
    		int[] result = pstmt.executeBatch();
    		pstmt.clearBatch();
    		return result;
    	} catch (SQLException ex) {
    		JDBCUtils.logError("DBERROR OCCURS: \\r\\n CODE-" + ex.getErrorCode()
                    + "  MESSAGE: " + ex.getMessage(), ex);
    		 throw new SQLNestedException("Execute sql batcher: ["+sql+"] error. ", ex);
    	} finally {
    		JDBCUtils.close(pstmt);
    	}
    }
}

